#include "cguimanager.h"

/**
 * CGuiManager - constructor
 */
CGuiManager::CGuiManager() {
  focusObjPtr = NULL;
  prelightObjPtr = NULL;
}
//---------------------------------------------------------------------------

/**
 * ~CGuiManager - destructor
 */
CGuiManager::~CGuiManager() {
  dialogs.clear();
}
//---------------------------------------------------------------------------

/**
 * setRendererPtr - sets pointer on gui renderer
 * @param rendererPtr
 */
void CGuiManager::setRendererPtr(CGuiRenderer* rendererPtr) {
  this->rendererPtr = rendererPtr;
}
//---------------------------------------------------------------------------

/**
 * setListenerPtr - sets pointer on gui listener
 * @param listenerPtr
 */
void CGuiManager::setListenerPtr(CGuiListener* listenerPtr) {
  this->listenerPtr = listenerPtr;
}
//---------------------------------------------------------------------------

/**
 * addDialogPtr - adds new dialog pointer into the list
 * @param dialogPtr
 */
void CGuiManager::addDialogPtr(CDialog* dialogPtr) {
  dialogs.push_back(dialogPtr);
}
//---------------------------------------------------------------------------

/**
 * applyStyle - applies graphical style on components controlled by manager
 * @param fileName
 * @param logPtr
 */
void CGuiManager::applyStyle(string fileName, CLogger* logPtr) {

  // Read default styles
  CDefaultStyles styles =
      CGuiDefaultStylesLoader::loadStyle(fileName, logPtr);

  // Go through dialogues
  for (vector<CDialog*>::iterator i = dialogs.begin(); i < dialogs.end(); i++) {

    // Temporary style for dialog component
    CGuiStyle tmpStyle;

    // Apply style on dialog
    if (styles.find(CGuiDefaultStylesLoader::DEFAULT_DIALOG,
        CGuiDefaultStylesLoader::STYLE_DEFAULT, tmpStyle)) {
      (*i)->setStyle(tmpStyle);
    }

    // Apply style on dialog components
    vector<CLayoutItem*>::iterator j = (*i)->getItemsPtr()->begin();
    for (; j < (*i)->getItemsPtr()->end(); j++) {

      // Temporary pointer on component
      CDynamicGuiObject* obj =
          dynamic_cast<CDynamicGuiObject*> ((*j)->getComponentPtr());

      // Determinate component type
      int cid(-1);
      if (dynamic_cast<CButton*> (obj)) {
        cid = CGuiDefaultStylesLoader::DEFAULT_BUTTON;
      } else if (dynamic_cast<CComboBox*> (obj)) {
        cid = CGuiDefaultStylesLoader::DEFAULT_COMBO;
      } else if (dynamic_cast<CSpinBox*> (obj)) {
        cid = CGuiDefaultStylesLoader::DEFAULT_SPIN;
      } else if (dynamic_cast<CLabel*> (obj)) {
        cid = CGuiDefaultStylesLoader::DEFAULT_LABEL;
      } else if (dynamic_cast<CEdit*> (obj)) {
        cid = CGuiDefaultStylesLoader::DEFAULT_EDIT;
      }

      // Find and apply styles for each state of component
      if (styles.find(cid, CGuiDefaultStylesLoader::STYLE_NORMAL, tmpStyle)) {
        obj->setStyleNormal(tmpStyle);
      }
      if (styles.find(cid, CGuiDefaultStylesLoader::STYLE_FOCUS, tmpStyle)) {
        obj->setStyleFocus(tmpStyle);
      }
      if (styles.find(cid, CGuiDefaultStylesLoader::STYLE_PRELIGHT, tmpStyle)) {
        obj->setStylePrelight(tmpStyle);
      }
      if (styles.find(cid, CGuiDefaultStylesLoader::STYLE_DISABLED, tmpStyle)) {
        obj->setStyleDisabled(tmpStyle);
      }
    }
  }
}
//---------------------------------------------------------------------------

/**
 * dispatchEvent - passes event from input to gui
 * @param eventPtr
 */
void CGuiManager::dispatchEvent(CEvent* eventPtr) {

  // Cast event to mouse or keyboard event
  CMouseEvent* me = dynamic_cast<CMouseEvent*> (eventPtr);
  CKeyboardEvent* ke = dynamic_cast<CKeyboardEvent*> (eventPtr);

  // Copy list of pointers on dialogues into temporary list and sort it
  // according to z axis descending
  vector<CDialog*> tmp = dialogs;
  sort(tmp.begin(), tmp.end(), TGreaterZ());

  // If mouse event is present, go through all dialogues, starting with the
  // one with greatest z axis position, and locate that one which triggered
  // the event
  if (me) {
    for (vector<CDialog*>::iterator i = tmp.begin(); i < tmp.end(); i++) {
      if ((*i)->isFocused(me)) {

        // Fowards event to dialog, retrieves pointer on focused component
        CGuiObject* tmpPtr = (*i)->dispatchMouseEvent(me);
        CDynamicGuiObject* tmpDPtr =
            dynamic_cast<CDynamicGuiObject*> (tmpPtr);

        // Cast mouse event to click or motion event
        CMouseEvent* mme = dynamic_cast<CMouseMoveEvent*> (me);
        CMouseEvent* mce = dynamic_cast<CMouseClickEvent*> (me);

        // If movement event is present, cancel prelight on last focused
        // component and prelight new one (if any is currently focused)
        // Otherwise if click event is present, set focus on clicked
        // component and foward its pointer to the listener
        if (mme) {
          if (prelightObjPtr) {
            resetComponentStatus(prelightObjPtr);
          }
          if (tmpDPtr) {
            prelightObjPtr = tmpDPtr;
            prelightObjPtr->setStyle(prelightObjPtr->getStylePrelight());
          }
        } else if (mce) {
          if (focusObjPtr) {
            resetComponentStatus(focusObjPtr);
          }
          if (tmpDPtr) {
            focusObjPtr = tmpDPtr;
            focusObjPtr->setStyle(focusObjPtr->getStyleFocus());
            CDynamicGuiObject* tmp =
                focusObjPtr->findHighestDynamicGuiObjectOwnerPtr();
            listenerPtr->doFocus(tmp);
          }
        }
        return;
      }
    }
  } else if (ke) {

    // Key press over active component
    if (focusObjPtr) {
      CDynamicGuiObject* tmp =
          focusObjPtr->findHighestDynamicGuiObjectOwnerPtr();
      if (tmp) {
        tmp->keyDown(ke->getKeyId(), ke->getUnicode());
      }
    }
  }
}
//---------------------------------------------------------------------------

/**
 * resetComponentStatus - cancels component prelight
 * @param compPtr
 */
void CGuiManager::resetComponentStatus(CDynamicGuiObject* compPtr) {
  if (compPtr->isDisabled()) {
    compPtr->setStyle(compPtr->getStyleDisabled());
  } else {
    compPtr->setStyle(compPtr->getStyleNormal());
  }
  compPtr = NULL;
}
//---------------------------------------------------------------------------

/**
 * drawGui - draw gui
 */
void CGuiManager::drawGui() {

  // Copy list of pointers on dialogues into temporary list and sort it
  // according to z axis ascending
  vector<CDialog*> tmp = dialogs;
  sort(tmp.begin(), tmp.end(), TLesserZ());

  // Draw dialogues
  for (vector<CDialog*>::iterator i = tmp.begin(); i < tmp.end(); i++) {
    (*i)->draw(rendererPtr);
  }
}
//---------------------------------------------------------------------------
